"""
篡改监测样本管理
"""

from flask import jsonify, g, current_app
from app.libs.redprint import RedPrint
from app.validators.base_page import (
    QueryBasePageForm,
    UpdateBasePageForm
)
from app.db.models.jobs import Job
from app.db.models.tasks import ChangeCheckBasepage
from app.db.models.asset_tasks import AssetTasks
from app.libs.utils import enable_update_change_pages
from app.log.logs import UChangeCheckPageLog


api = RedPrint('base_page')


@api.route("/list", methods=["GET"])
def get_base_page_list():
    """查询样本"""
    form = QueryBasePageForm().validate_for_api()
    if g.role.name == '管理员':
        page_query = {"uid": form.uid}
    else:
        page_query = {"uid": g.user.id}
    job_query = {}
    if target_name := form.target_name.data:
        job_query.update({"target_name": {"$regex": target_name}})
    if target_url := form.target_url.data:
        job_query.update({"target_url": {"$regex": target_url}})
    limit = form.limit.data
    page = form.page.data
    agg = [
        {"$match": page_query},
        {"$project": {"job_id": 1, "task_id": 1, "uid": 1, "status": 1, "updated_at": 1, "url": 1}},
        {"$lookup": {"from": "jobs", "localField": "job_id", "foreignField": "_id", "as": "job"}},
        {"$lookup": {"from": "users", "localField": "uid", "foreignField": "_id", "as": "user"}},
        {"$project": {
            "job_id": 1, "task_id": 1, "status": 1, "updated_at": 1, "url": 1,
            "target_url": "$job.targetUrl", "target_name": "$job.note",
            "username": "$user.username"
        }},
        {"$match": job_query},
        {"$sort": {"updated_at": -1}},
        {"$group": {
            "_id": "$job_id",
            "count": {"$sum": 1},
            "urls": {"$push": "$url"},
            "updated_at": {"$last": "$updated_at"},
            "status": {"$last": "$status"},
            "task_id": {"$last": "$task_id"},
            "target_url": {"$last": "$target_url"},
            "target_name": {"$last": "$target_name"},
            "username": {"$last": "$username"}}
        },
    ]
    all_pages = list(ChangeCheckBasepage.objects.aggregate(agg))
    total = len(all_pages)
    result = []
    for i in all_pages[(page - 1) * limit: limit * page]:
        result.append({
            "job_id": i["_id"],
            "page_count": i["count"],
            "target_name": i["target_name"][0] if i["target_name"] else "",
            "target_url": i["target_url"][0] if i["target_url"] else "",
            "username": i["username"][0] if i["username"] else "",
            "status": i["status"],
            "updated_at": i["updated_at"],
            "task_id": i["task_id"],
            "urls": i["urls"]
        })
    return jsonify({"code": 200, "status": "success",
                    "data": {"count": total, "limit": limit, "page": page, "result": result}})


@api.route("/update", methods=["POST"])
def update_base_page():
    """更新样本"""
    form = UpdateBasePageForm().validate_for_api()
    task_ids = form.task_ids.data or []
    page_query = {"task_id": {"$in": task_ids}}
    if g.role.name != '管理员':
        page_query.update({"uid": g.user.id})
    page_maps = {
        p.task_id: p.job_id for p in ChangeCheckBasepage.objects.find(page_query).only("uid", "job_id", "task_id")
    }
    job_maps = {j.id: j for j in Job.objects.filter(id__in=list(page_maps.values())).only(
        "note", "targetUrl", "id", "enable_proxy_ip", "sourceIp", "target", "uid"
    )}
    targets = []
    log_msg = []
    for at in AssetTasks.objects.find(
            {"changeCheckSettings.taskId": {"$in": list(page_maps.keys())}}
    ).only("changeCheckSettings", "prelogin", "jobId", "scanSpeedConfig"):
        settings = at.changeCheckSettings
        job = job_maps.get(page_maps.get(settings.taskId, ""))
        if not job:
            continue
        try:
            enable_update_change_pages(asset_task=at, job=job)
        except Exception as e:
            current_app.logger.warning(f"更新样本{job.targetUrl}({job.id})失败, {e}")
            continue
        else:
            ChangeCheckBasepage._get_collection().update_many(
                {"task_id": settings.taskId},
                {"$set": {"status": "waiting"}}
            )
            targets.append(job.targetUrl)
            log_msg.append(f"{job.note}({job.targetUrl})")
    if targets:
        log_info = {
            'affects': targets,
            'actionMessage': "篡改监测样本更新",
            'detail': f'篡改监测样本更新，资产名称(地址): {log_msg}'
        }
        UChangeCheckPageLog(**log_info).info(log_info['actionMessage'], log_info['detail'])
    return jsonify({'code': 200, 'message': f'更新任务下发成功{len(targets)}个', 'status': 'success'})
